﻿using System;
using System.Collections.Generic;
using SimpleJSON;

namespace ConfigTool
{
    public class AutoCreateCode
    {
        private string savePath;
        private Dictionary<string, JSONClass> jsonDic = new Dictionary<string, JSONClass>();

        public AutoCreateCode(string _savePath, Dictionary<string, JSONClass> _jsonDic)
        {
            savePath = _savePath;
            jsonDic = _jsonDic;

            Tool.CreateDirectory(savePath);
        }

        public void CreateCodeFiles()
        {
            Tool.ClearFiles(savePath);
            foreach (var a in jsonDic)
            {
                string path = string.Format("{0}\\Config{1}.cs", savePath, a.Key);
                Tool.CreateFile(path, CreateDataCode(a.Key));
            }
        }

        private string CreateDataCode(string _configTitle)
        {
            string codeStart = CreateCodeStart(_configTitle);
            string dataCode = CreateDataClass(_configTitle);
            string manager = CreateDataManager(_configTitle);
            string codeEnd = CreateCodeEnd();

            return string.Concat(codeStart, dataCode, manager, codeEnd);
        }

        #region 创建数据代码
        private string CreateCodeStart(string _title)
        {
            string codeNameSpace1 = "using System.Collections.Generic;\n";
            string codeNameSpace2 = "using System.Collections;\n";
            string codeNameSpace3 = "using UnityEngine;\n";
            string codeNameSpace4 = "using SimpleJSON;\n";
            string codeCurNameSpace = "namespace ConfigTool\n{\n";

            return string.Concat(codeNameSpace1, codeNameSpace2, codeNameSpace3, codeNameSpace4,
                codeCurNameSpace);
        }

        private string CreateDataClass(string _title)
        {
            string start = "\tpublic class Config" + _title + "Data\n\t{\n";
            string defineVariateCode = CreateVariate(_title);
            string defineConstructorCode = CreateConstructor(_title);
            string end = "\t}\n";
            return string.Concat(start, defineVariateCode, defineConstructorCode, end);
        }

        private string CreateCodeEnd()
        {
            return "}\n";
        }

        private string CreateVariate(string _title)
        {
            JSONClass curConfig = jsonDic[_title];
            JSONNode key = curConfig["variate"];
            JSONNode annotation = curConfig["annotation"];
            JSONNode variateType = curConfig["type"];

            string rtnValue = string.Empty;
            for (int i = 0; i < key.Count; i++)
            {
                string variateName = key[i];
                string annotationDetial = annotation[variateName];
                string type = variateType[variateName];

                string codeVariate = string.Concat(
                    CreateAnnotation(annotationDetial),
                    CreateVariate(type, variateName));

                rtnValue = string.Concat(rtnValue, codeVariate);
            }
            return rtnValue;
        }

        private string CreateConstructor(string _title)
        {
            JSONClass curConfig = jsonDic[_title];
            JSONNode key = curConfig["variate"];
            JSONNode annotation = curConfig["annotation"];
            JSONNode variateType = curConfig["type"];

            string rtnValue = string.Format("\t\tpublic Config{0}Data(JSONNode _jsonNode)\n\t\t", _title) + "{\n";
            for (int i = 0; i < key.Count; i++)
            {
                string variateName = key[i];
                string type = variateType[variateName];
                string codeValuation = CreateValuation(variateName, type, "_jsonNode");
                rtnValue = string.Concat(rtnValue, codeValuation);
            }
            string constructorEnd = "\t\t}\n";
            rtnValue = string.Concat(rtnValue, constructorEnd);

            return rtnValue;
        }

        private string CreateDataManager(string _title)
        {
            string start = string.Format("\n\tpublic class Config{0} : ConfigBase\n", _title) + "\t{\n";
            string dicDefine = string.Format("\t\tprivate Dictionary<int, Config{0}Data> dic = new Dictionary<int, Config{0}Data>();\n", _title);

            string constructor = string.Format("\t\tpublic Config{0}(JSONClass _json)\n", _title)
                + "\t\t{\n\t\t\tfor (int i = 3; i < _json.Count; i++)\n\t\t\t{\n"
                + string.Format("\t\t\t\tint key = i - 1;\n\t\t\t\tConfig{0}Data data = new Config{0}Data(_json[i]);\n\t\t\t\tdic.Add(key, data);\n", _title)
                + "\t\t\t}\n\t\t}\n";

            string getDataFunction = string.Format("\t\tpublic Config{0}Data GetData(int _id)\n", _title)
                + "\t\t{\n\t\t\tif (!dic.ContainsKey(_id))\n\t\t\t{\n\t\t\t\tDebug.LogError(\"没有指定Id\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn dic[_id];\n\t\t}\n";

            string end = "\t}\n";

            return string.Concat(start, dicDefine, constructor, getDataFunction, end);
        }
        //创建变量赋值代码,目前不支持枚举，字典类型
        private string CreateValuation(string _variateName, string _type, string _jsonNodeName)
        {
            string rtnValue = string.Format("\t\t\t{0} = ", _variateName);
            if (_type.Contains("List"))
            {
                rtnValue = CreateReferenceTypeValuation(_variateName, _type, _jsonNodeName);
            }
            else
            {
                rtnValue = string.Concat(rtnValue, CreateValueTypeValuation(_variateName, _type, _jsonNodeName));
            }
            return rtnValue;
        }

        //创建值类型赋值（等号后面部分）
        private string CreateValueTypeValuation(string _variateName, string _type, string _jsonNodeName)
        {
            string rtnValue = string.Empty;
            switch (_type)
            {
                case "int":
                    rtnValue = string.Format("int.Parse({0}[\"{1}\"]);\n", _jsonNodeName, _variateName);
                    break;
                case "float":
                    rtnValue = string.Format("float.Parse({0}[\"{1}\"]);\n", _jsonNodeName, _variateName);
                    break;
                case "bool":
                    rtnValue = string.Format("bool.Parse({0}[\"{1}\"]);\n", _jsonNodeName, _variateName);
                    break;
                case "string":
                    rtnValue = string.Format("{0}[\"{1}\"];\n", _jsonNodeName, _variateName);
                    break;
                default:
                    Console.WriteLine("创建的类型不对");
                    break;
            }
            return rtnValue;
        }

        //创建引用类型赋值，目前只支持list
        private string CreateReferenceTypeValuation(string _variateName, string _type, string _jsonNodeName)
        {
            if (!_type.Contains("List"))
            {
                Console.WriteLine("传入类型错误，应该是List");
                return string.Empty;
            }
            string[] typeDetials = _type.Split('<', '>');
            if (typeDetials.Length < 3)
            {
                Console.WriteLine("输入的list类型格式错误！");
            }
            string rtnValue = string.Empty;
            rtnValue = string.Format("\t\t\tstring {0}Value = {1}[\"{0}\"];\n\t\t\tstring[] {0}Values = {0}Value.Split(',');\n\t\t\t", _variateName, _jsonNodeName);
            switch (typeDetials[1])
            {
                case "int":
                    rtnValue += "foreach(var a in " + _variateName + "Values)\n\t\t\t{\n\t\t\t\t" + _variateName + ".Add(int.Parse(a));\n\t\t\t}\n";
                    break;
                case "float":
                    rtnValue += "foreach(var a in " + _variateName + "Values)\n\t\t\t{\n\t\t\t\t" + _variateName + ".Add(float.Parse(a));\n\t\t\t}\n";
                    break;
                case "string":
                    rtnValue += "foreach(var a in " + _variateName + "Values)\n\t\t\t{\n\t\t\t\t" + _variateName + ".Add(a);\n\t\t\t}\n";
                    break;
                case "bool":
                    rtnValue += "foreach(var a in " + _variateName + "Values)\n\t\t\t{\n\t\t\t\t" + _variateName + ".Add(bool.Parse(a));\n\t\t\t}\n";
                    break;
                default:
                    Console.WriteLine("list中具体类型错误");
                    break;
            }
            return rtnValue;
        }

        //创建无参数注释
        private string CreateAnnotation(string _value)
        {
            string rtnValue = string.Format("\t\t/// <summary>\n\t\t/// {0}\n\t\t/// </summary>\n", _value);
            return rtnValue;
        }

        //创建变量
        private string CreateVariate(string _type, string _name)
        {
            string rtnValue = string.Empty;
            rtnValue = string.Format("\t\tpublic readonly {0} {1}", _type, _name);
            if (_type.Contains("List") || _type.Contains("Dictionary"))
            {
                rtnValue += string.Format(" = new {0}()", _type);
            }
            rtnValue += ";\n";
            return rtnValue;
        }
        #endregion 创建数据代码
    }
}
